/**********************************
 * Library to make use of Lists
 *
 * @author Jorge Machado
 * @date 12-12-2008
 *
 */
#ifndef _LISTAS_C
#define _LISTAS_C

#include <stdio.h>
#include <stdlib.h>
#include "listas.h"

/**
 * Create an empty list
 */

List * createNewList()
{
	List * newList = malloc(sizeof(struct List_Struct));
	newList->firstElement = NULL;
	newList->lastElement = NULL;
	newList->size = 0;
	return newList;
}

/**
 * Remove an element from the list and update first, last element and size
 */
void * lstRemoveElement(List * l, int i)
{
	ListNode * node;
	int iter;
	void * element = NULL;
	if(i < l->size)
	{
		if(i == 0)
		{
			if(l->size == 1)
			{
				element = l->firstElement;
				l->firstElement = NULL;
				l->lastElement = NULL;
			}
			else
			{
				element = l->firstElement;
				l->firstElement = l->firstElement->next;
				l->firstElement->previous = NULL;
			}
		}
		else if(i == l->size - 1)
		{
			element = l->lastElement;
			l->lastElement = l->lastElement->previous;
			l->lastElement->next = NULL;
		}
		else
		{
			node = l->firstElement;
			for(iter = 1; iter <= i; iter++)
			{
				node = node->next;
			}
			element = node;
			node->previous->next = node->next;
			node->next->previous = node->previous;
		}
		l->size = l->size - 1;
	}
	return element;
}

/**
 * Add an element to a list in last position
 */
void lstAddElement(List * l, void * element)
{
	if(element == NULL)
		return;
	if(l == NULL)
		return;
	if(l->size == 0)
	{
		l->firstElement = malloc(sizeof(ListNode));
		l->lastElement = l->firstElement;
		l->size=1;
		l->firstElement->element = element;
	}
	else
	{
		l->lastElement->next = malloc(sizeof(ListNode));
		l->lastElement->next->previous=l->lastElement;
		l->lastElement = l->lastElement->next;
		l->lastElement->element = element;
		l->size = l->size+1;
	}
}

/**
 * Add an element to a list in first position
 */
void lstAddElementInBegin(List * l, void * element)
{
	if(element == NULL)
		return;
	if(l == NULL)
		return;
	if(l->size == 0)
	{
		l->firstElement = malloc(sizeof(ListNode));
		l->lastElement = l->firstElement;
		l->size=1;
		l->firstElement->element = element;
	}
	else
	{
		l->firstElement->previous = malloc(sizeof(ListNode));
		l->firstElement->previous->next=l->firstElement;
		l->firstElement = l->firstElement->previous;
		l->firstElement->element = element;
		l->size = l->size+1;
	}
}

/**
 * Return the element at given position
 */
void * lstGetElement(List * l, int i)
{
	ListNode * node = l->firstElement;

	int iter;
	if(l == NULL)
		return NULL;
	if(l->firstElement == NULL)
		return NULL;
	if(i >= l->size)
		return NULL;
	if(i == 0)
		return node->element;
	for(iter = 1; iter <= i; iter++)
	{
		node = node->next;
	}
	return node->element;
}

/**
 * Return the first element in a list
 */
void * firstElement(List * list)
{
	if(list == NULL || list->size == 0)
		return NULL;
	return list->firstElement->element;
}

/**
 * Return the second element in a list
 */
void * secondElement(List * list)
{
	if(list == NULL || list->size <= 1)
		return NULL;
	return list->firstElement->next->element;
}
/**
 * Return the third element in a list
 */
void * thirdElement(List * list)
{
	if(list == NULL || list->size <= 2)
		return NULL;
	return list->firstElement->next->next->element;
}

/**
 * Return the last element in a list
 */
void * lastElement(List * list)
{
	if(list == NULL)
		return NULL;
	return list->lastElement->element;
}

/**
 * Return list size
 */
int lstSize(List * l)
{
	if (l == NULL)
		return 0;
	return l->size;
}

/*
 * Creata a copy of the list, don't copy elements, elements will be the same, will use pointers
*/
List * copyList (List * l)
{
	int i;
	List * returnL;
	if(l != NULL)
	{
		returnL = createNewList();
		for(i=0;i < lstSize(l);i++)
		{
			lstAddElement(returnL,lstGetElement(l,i));
		}
	}
	return returnL;

}

#else
/* code to include if the token is defined */
#endif

